package hos.net.soap

import android.util.Base64
import com.drake.net.interfaces.ProgressListener
import com.drake.net.request.BaseRequest
import com.drake.net.request.Method
import com.drake.net.request.setConverter
import com.drake.net.request.uploadListeners
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONArray
import org.json.JSONObject
import org.ksoap2.SoapConst
import org.ksoap2.SoapContentType
import org.ksoap2.SoapEnvelope
import org.ksoap2.serialization.SoapObject
import org.ksoap2.serialization.SoapSerializationEnvelope
import org.kxml2.kdom.Element
import org.kxml2.kdom.Node

/**
 * <p>Title: SoapRequest </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2024-04-08 20:55
 * @version : 1.0
 */
open class SoapRequest(
    private val methodName: String,
    private val nameSpace: String = Soap.nameSpace
) :
    BaseRequest() {
    // 设置Soap对象
    private val soapObject by lazy { SoapObject(nameSpace, methodName) }
    private var headerBody = arrayOf<Element>(Element().createElement(nameSpace, "SoapHeader"))


    open var dotNet = Soap.dotNet

    open var version = Soap.version

    //<editor-fold desc="Header">
    /**
     * 请求方法
     */
    override var method = Method.POST

    private fun addHeaderElement(name: String, value: Any?) {
        val element = Element().createElement(nameSpace, name)
        element.addChild(Node.TEXT, value)
        this.headerBody[0].addChild(Node.ELEMENT, element)
    }

    /**
     * 添加请求头
     * 如果已存在相同`name`的请求头会添加而不会覆盖, 因为请求头本身存在多个值
     */
    fun addHeaderBody(name: String, value: String) {
        addHeaderElement(name, value)
    }

    /**
     * 批量设置请求头
     */
    fun setHeaderBody(headers: Array<Element>) {
        this.headerBody = headers
    }
    //</editor-fold>

    //<editor-fold desc="Param">
    override fun param(name: String, value: Boolean?) {
        soapObject.addProperty(name, value)
    }

    override fun param(name: String, value: Number?) {
        soapObject.addProperty(name, value)
    }

    override fun param(name: String, value: String?) {
        soapObject.addProperty(name, value)
    }

    override fun param(name: String, value: String?, encoded: Boolean) {
        value ?: return
        if (encoded) {
            soapObject.addProperty(name, Base64.encodeToString(value.toByteArray(), Base64.NO_WRAP))
        } else {
            soapObject.addProperty(name, value)
        }
    }

    fun param(namespace: String, name: String, value: Boolean?) {
        soapObject.addProperty(namespace, name, value)
    }

    fun param(namespace: String, name: String, value: Number?) {
        soapObject.addProperty(namespace, name, value)
    }

    fun param(namespace: String, name: String, value: String?) {
        soapObject.addProperty(namespace, name, value)
    }
    //</editor-fold>
    //<editor-fold desc="JSON">
    /**
     * 添加Json
     */
    fun json(name: String, json: String?) {
        soapObject.addProperty(name, json)
    }

    /**
     * 添加Json
     */
    fun json(name: String, json: JSONObject?) {
        soapObject.addProperty(name, json?.toString())
    }

    /**
     * 添加Json
     */
    fun json(name: String, json: JSONArray?) {
        soapObject.addProperty(name, json?.toString())
    }

    /**
     * 添加Json为请求体
     */
    fun json(name: String, json: Map<String, Any?>?) {
        soapObject.addProperty(name, JSONObject(json ?: return).toString())
    }

    /**
     * 添加Json对象为请求体
     */
    fun json(name: String, vararg json: Pair<String, Any?>) {
        soapObject.addProperty(name, JSONObject(json.toMap()).toString())
    }
    //</editor-fold>
    /**
     * 添加上传进度监听器
     */
    fun addUploadListener(progressListener: ProgressListener) {
        okHttpRequest.uploadListeners().add(progressListener)
    }


    private fun getContentType(): String {
        return if (version == SoapConst.VER12) {
            SoapContentType.SOAP_XML_CHARSET_UTF_8
        } else SoapContentType.XML_CHARSET_UTF_8
    }

    override fun buildRequest(): Request {
        // 添加Header
        addHeader("User-Agent", SoapConst.USER_AGENT)
        if (version != SoapConst.VER12) {
            addHeader("SOAPAction", nameSpace + methodName)
        }
        // 设置Soap消息
        val envelope = SoapSerializationEnvelope(version)
        // 设置是否调用的是dotNet开发的WebService
        envelope.dotNet = dotNet
        envelope.headerOut = headerBody
        envelope.setOutputSoapObject(soapObject)
        val requestData = envelope.createRequestData()
        // 添加Tag 在过滤器 OkHttpSoapInterceptor 中进行解析XML
        tag<SoapSerializationEnvelope>(
            SoapSerializationEnvelope::class.java,
            envelope
        )
        return okHttpRequest.method(
            method.name,
            requestData.toRequestBody(getContentType().toMediaType())
        ).url(httpUrl.build())
            .setConverter(converter)
            .build()
    }
}
